import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import net.canos.object.Resultado;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;

import com.canos.util.Comparador;
import com.canos.util.Util;


public class SystemInfoMultiThread {

	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Util.p("");
		Util.p("versión multi thread");
		
		ArrayList<Resultado> resultados = new ArrayList<Resultado>();
		int numElems = 2000000;
		int tamanyoCadena = 50;
		ArrayList<String> list1 = new ArrayList<String>();
		ArrayList<String> list2 = new ArrayList<String>();
		
		
		int numProcessors = Runtime.getRuntime().availableProcessors();

		Util.p("Numero de hilos que vamos a usar:"+numProcessors);
		Util.p("Start");
		Util.printMemoryInfo();
		Util.p("");Util.p("");
		
		// Creación de palabras aleatorias
		Util.p("Generando cadenas...");
		long pre0 = System.currentTimeMillis();
		
		for(int i = 0;i<numElems;i++){
			String aux1 = RandomStringUtils.randomAscii(tamanyoCadena);
		    String aux2 = RandomStringUtils.randomAscii(tamanyoCadena);		    
			list1.add(aux1);
			list2.add(aux2);
		}
		long pos0 = System.currentTimeMillis();
		Util.p("Generadas cadenas ("+(pos0-pre0)+")");
		Util.printMemoryInfo();
		Util.p("");Util.p("");
		
		
		
		// Confrontar dos cadenas
		Util.p("Enfrentando cadenas y calculando semejanza...");
		long pre1 = System.currentTimeMillis();
		
		ExecutorService executor = Executors.newFixedThreadPool(numProcessors);
		
	    List<Comparador> misComparadores = new ArrayList<Comparador>();
	    misComparadores.add(new Comparador(list1,list2,numElems));
	    misComparadores.add(new Comparador(list1,list2,numElems));
	    
	    List<Future<ArrayList<Resultado>>> futures;
		try {
			futures = executor.invokeAll(misComparadores);
			Util.p("Resultado obtenidos:"+futures.size());
			int i = 1;
		    for(Future<ArrayList<Resultado>> future : futures){
		    	Util.p("Resultado thread #"+i+":"+future.get().size());
		    	resultados.addAll(future.get());
		    	i++;
		    }
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		
	    executor.shutdown();
	    
	    
		
		long pos1 = System.currentTimeMillis();
		Util.p("Calculadas distancias ("+(pos1-pre1)+")");
		Util.printMemoryInfo();
		Util.p("");Util.p("");;
		
		
		// reordenar 
		long pre2 = System.currentTimeMillis();
		Collections.sort(resultados);
		long pos2 = System.currentTimeMillis();
		
		Util.p("Ordenadas cadenas ("+(pos2-pre2)+")");
		Util.printMemoryInfo();
		Util.p("");Util.p("");;
		
		// tiempos
		Long tiempo = (pos2-pre2) + (pos1-pre1) +  (pos0-pre0);
		Util.p("Creando cadenas:"+(pos0-pre0));
		Util.p("Comparando:"+(pos1-pre1));
		Util.p("Ordenando:"+(pos2-pre2));
		Util.p("Tiempo empleado:"+tiempo+"ms");
		Util.p("");Util.p("");
		
		
		// ranking
		Util.p("RANKING resultados:"+resultados.size());
		for(int i=0;i<3;i++){
			Util.p((i+1)+")"+resultados.get(i));
		}
		
		
		Util.p("");Util.p("");
		Util.printMemoryInfo();
		Util.p("");Util.p("");
		
		Util.p("Fuerzo un GC");
		System.gc();
		
		Util.printMemoryInfo();
		Util.p("");Util.p("");;
		
		
	}

}
